#pragma once
#include "pch.h"
#pragma warning(disable:4200)
#define HeadSize (sizeof(MemoryHead))
class Session;
typedef struct _MemoryHead {
	union {
		struct _MemoryHead* next;
		char* cnext;
	};
	union {
		Session* ihandle;
		void* vhandle;
	};
	DWORD				tm;
	DWORD				use;
	char				buf[];
}MemoryHead, * PMemoryHead;

class LoopBuffer
{
	char* _buf;
	char* _top;
	char* _end;
	char* _eof;
	HANDLE hEmpty;
	CRITICAL_SECTION csLock;
	HANDLE	flushTimer;
	HANDLE	hTimerQueue;
	__declspec (noinline) char* tryGet(size_t reqsize);
	__declspec (noinline) PMemoryHead realGet(void* handle, char* p, size_t reqsize);
	static VOID CALLBACK TimerRoutine(LoopBuffer& pool, BOOLEAN TimerOrWaitFired);
public:
	LoopBuffer(size_t size) :
		flushTimer(INVALID_HANDLE_VALUE),
		hTimerQueue(INVALID_HANDLE_VALUE)
	{
		_buf = new char[size];
		_top = _buf;
		_end = _buf;
		_eof = _buf + size - HeadSize;
		InitializeCriticalSection(&csLock);
		hTimerQueue = CreateTimerQueue();
		CreateTimerQueueTimer(&flushTimer, hTimerQueue,
			(WAITORTIMERCALLBACK)TimerRoutine, this, 1 * 1000, 1 * 1000, 0);
	}
	~LoopBuffer() {
		DeleteTimerQueueTimer(hTimerQueue, flushTimer, NULL);
		DeleteTimerQueue(hTimerQueue);
		RELEASE(_buf);
		DeleteCriticalSection(&csLock);
	}

	char* get(void* handle, size_t size) {
		char* p;
		size += HeadSize;
		size = (size + 7) & (~7);
		EnterCriticalSection(&csLock);
		p = tryGet(size);
		if (p) {
			PMemoryHead ph = realGet(handle, p, size);
			p = ph->buf;
		}
		LeaveCriticalSection(&csLock);
		return p;
	}
	void free(char* buf) {
		PMemoryHead p;
		p = (PMemoryHead)(buf - HeadSize);
		EnterCriticalSection(&csLock);
		p->use = 0;
		p->vhandle = NULL;
		if ((char*)p == _end) {
			while ((p->use == 0) && ((char*)p != _top)) {
				p = p->next;
			}
			_end = (char*)p;
		}
		LeaveCriticalSection(&csLock);
		return;
	}
};
